<template>
  <div class="content">
    <h1 class="seo-title">文本比较 - 在线文本差异对比</h1>
    <div class="tool-bar">
      <button class="bar-btn" @click="compareTexts">比较</button>
      <label class="text-title"><input type="checkbox" v-model="ignoreWhitespace">忽略空白差异</label>
    </div>
    <div class="text-content">
      <Codemirror
        class="input-editor"
        v-model:value="leftText"
        border
        height="560"
        width="640"
        :options="cmRef"
      />
      <Codemirror
        class="output-editor"
        v-model:value="rightText"
        border
        height="560"
        width="640"
        :options="cmRef"
      />
    </div>
    <div class="tool-bar">
      <p class="text-title">不一样的文本（逐行比对，左/右各自单独输出）</p>
    </div>
    <div class="text-content">
      <Codemirror
        class="output-editor"
        v-model:value="leftOnlyText"
        border
        height="280"
        width="640"
        :options="outRef"
      />
      <Codemirror
        class="output-editor"
        v-model:value="rightOnlyText"
        border
        height="280"
        width="640"
        :options="outRef"
      />
    </div>
  </div>
</template>

<script>
import "codemirror/mode/javascript/javascript.js"
import "codemirror/mode/xml/xml.js"
import Codemirror from "codemirror-editor-vue3"

export default {
  components: { Codemirror },
  data () {
    return {
      leftText: "",
      rightText: "",
      leftOnlyText: "",
      rightOnlyText: "",
      ignoreWhitespace: true,
      cmRef: {
        mode: "text/plain",
        lineWrapping: true
      },
      outRef: {
        mode: "text/plain",
        readOnly: true,
        lineWrapping: true
      }
    }
  },
  methods: {
    normalizeLine(line) {
      if (!this.ignoreWhitespace) return line
      return line.replace(/\s+/g, " ").trim()
    },
    event(act) {
        try {
          LA.track(act);
        } catch (e) {
          console.log(e)
        }
    },
    compareTexts() {
      this.event('compare');
      const leftLines = (this.leftText || "").split("\n")
      const rightLines = (this.rightText || "").split("\n")

      // 使用 Map 记录规范化行到原始行的多重映射，便于保留原始文本
      const leftMap = new Map()
      for (const line of leftLines) {
        const key = this.normalizeLine(line)
        const arr = leftMap.get(key) || []
        arr.push(line)
        leftMap.set(key, arr)
      }
      const rightMap = new Map()
      for (const line of rightLines) {
        const key = this.normalizeLine(line)
        const arr = rightMap.get(key) || []
        arr.push(line)
        rightMap.set(key, arr)
      }

      // 逐行统计差异（多重计数）
      const onlyLeft = []
      const onlyRight = []

      // 左侧独有
      for (const [key, arr] of leftMap.entries()) {
        const lcount = arr.length
        const rcount = (rightMap.get(key) || []).length
        if (lcount > rcount) {
          // 多出的次数保留原始行
          for (let i = 0; i < lcount - rcount; i++) {
            onlyLeft.push(arr[i])
          }
        }
      }
      // 右侧独有
      for (const [key, arr] of rightMap.entries()) {
        const rcount = arr.length
        const lcount = (leftMap.get(key) || []).length
        if (rcount > lcount) {
          for (let i = 0; i < rcount - lcount; i++) {
            onlyRight.push(arr[i])
          }
        }
      }

      this.leftOnlyText = onlyLeft.join("\n")
      this.rightOnlyText = onlyRight.join("\n")
    }
  }
}
</script>

<style scoped>
.content {
  text-align: left;
}
.tool-bar { 
  text-align: left;
  margin: 2px auto;
  width: 1324px;
}
.text-content {
  display: flex;
  justify-content: center;
  align-items: center;
}
.bar-btn {
  margin-right: 4px;
  color: #333;
}
.text-title {
  color: #333;
  margin-left: 4px;
  font-size: 12px;
}
.seo-title {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
</style>


